﻿using System;
using System.Runtime.InteropServices;

namespace VNMessageBox
{
	public sealed class CSysMsgBoxHook
	{
		#region  API Declarations

		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

		[DllImport("user32.dll")]
		private static extern int UnhookWindowsHookEx(IntPtr idHook);

		[DllImport("user32.dll")]
		private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);

		[DllImport("user32.dll")]
		private static extern bool SetDlgItemTextW(IntPtr hWnd, int nIDDlgItem, IntPtr lpString);

		[DllImport("gdi32.dll", EntryPoint = "CreateFontA", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
		public static extern int CreateFont(int H, int W, int E, int O, int W_, int I, int u, int S, int C, int OP, int CP, int Q, int PAF, string F);

		[DllImport("user32.dll", EntryPoint = "SendMessageA", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);

		[DllImport("user32.dll", EntryPoint = "SetWindowTextW", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
		public static extern int SetWindowText(IntPtr hwnd, IntPtr lpString);

		[DllImport("user32.dll", EntryPoint = "FindWindowExA", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
		public static extern int FindWindowEx(IntPtr hWnd1, int hWnd2, string lpsz1, string lpsz2);

		#endregion

		#region  Delegates

		private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

		#endregion

		#region  Private Constants

		#region  System

		private const long WH_CBT = 0x5;
		private const long HCBT_ACTIVATE = 0x5;

		#endregion

		#region  Buttons

		private const int ID_BUT_OK = 0x1;
		private const int ID_BUT_CANCEL = 0x2;
		private const int ID_BUT_ABORT = 0x3;
		private const int ID_BUT_RETRY = 0x4;
		private const int ID_BUT_IGNORE = 0x5;
		private const int ID_BUT_YES = 0x6;
		private const int ID_BUT_NO = 0x7;

		private const string BUT_OK = "Đồng Ý";
		private const string BUT_CANCLE = "Hủy Bỏ";
		private const string BUT_ABORT = "Hủy";
		private const string BUT_RETRY = "Làm Lại";
		private const string BUT_IGNORE = "Bỏ Qua";
		private const string BUT_YES = "Có";
		private const string BUT_NO = "Không";

		#endregion

		#endregion

		#region  Private Variables

		private IntPtr _hook;

		#endregion

		#region  Public Methods

		public void HookDialog()
		{
			this.UnHookDialog();

			_hook = SetWindowsHookEx((int)WH_CBT, new HookProc(DialogHookProc), IntPtr.Zero, AppDomain.GetCurrentThreadId());
		}

		public void UnHookDialog()
		{
			if (!_hook.Equals(IntPtr.Zero))
			{
				UnhookWindowsHookEx(_hook);
			}
		}

		#endregion

		#region  Private Functions

		private IntPtr DialogHookProc(int nCode, IntPtr wParam, IntPtr lParam)
		{
			if (nCode < 0)
			{
				return CallNextHookEx(_hook, nCode, wParam, lParam);
			}

			if (nCode == HCBT_ACTIVATE)
			{
				SetDlgItemTextW(wParam, ID_BUT_OK, Marshal.StringToHGlobalUni(BUT_OK));
				SetDlgItemTextW(wParam, ID_BUT_CANCEL, Marshal.StringToHGlobalUni(BUT_CANCLE));
				SetDlgItemTextW(wParam, ID_BUT_ABORT, Marshal.StringToHGlobalUni(BUT_ABORT));
				SetDlgItemTextW(wParam, ID_BUT_RETRY, Marshal.StringToHGlobalUni(BUT_RETRY));
				SetDlgItemTextW(wParam, ID_BUT_IGNORE, Marshal.StringToHGlobalUni(BUT_IGNORE));
				SetDlgItemTextW(wParam, ID_BUT_YES, Marshal.StringToHGlobalUni(BUT_YES));
				SetDlgItemTextW(wParam, ID_BUT_NO, Marshal.StringToHGlobalUni(BUT_NO));

				UnhookWindowsHookEx(_hook);
			}

			return CallNextHookEx(_hook, nCode, wParam, lParam);
		}

		#endregion
	}
}